from http import HTTPStatus
from typing import Any, Dict, Optional
from uuid import uuid4

from flask import Blueprint, g, jsonify, request
from werkzeug.security import check_password_hash, generate_password_hash

from . import data_store, nlp_service, email_service

api_bp = Blueprint("api", __name__)


def _sanitize_user(user: Dict[str, object]) -> Dict[str, object]:
    return {
        "id": user["id"],
        "username": user.get("username") or user.get("email", "").split("@")[0],
        "email": user.get("email"),
        "avatar": user.get("avatar"),
        "bio": user.get("bio"),
        "created_at": user.get("created_at"),
    }


def _get_token() -> Optional[str]:
    auth_header = request.headers.get("Authorization")
    if not auth_header:
        return None
    if auth_header.lower().startswith("bearer "):
        return auth_header.split(" ", 1)[1]
    return auth_header


def _get_current_user() -> Optional[Dict[str, object]]:
    token = _get_token()
    if not token:
        return None
    user_id = data_store.get_user_id_by_token(token)
    if not user_id:
        return None
    return data_store.get_user(user_id)


@api_bp.before_request
def load_current_user():
    g.current_user = _get_current_user()


def _serialize_comment(comment: Dict[str, Any]) -> Dict[str, Any]:
    author = data_store.get_user(comment["author_id"])
    return {
        "id": comment["id"],
        "author_id": comment["author_id"],
        "target_type": comment["target_type"],
        "target_id": comment["target_id"],
        "content": comment["content"],
        "created_at": comment["created_at"],
        "author": _sanitize_user(author) if author else None,
    }


@api_bp.post("/auth/send-verify-code")
def send_verify_code():
    """发送邮箱验证码"""
    payload = request.get_json(silent=True)
    if not payload:
        return jsonify({"error": "Invalid JSON payload"}), HTTPStatus.BAD_REQUEST

    email = payload.get("email", "").strip().lower()
    if not email:
        return jsonify({"error": "邮箱地址不能为空"}), HTTPStatus.BAD_REQUEST

    # 验证邮箱格式
    import re
    email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    if not re.match(email_pattern, email):
        return jsonify({"error": "邮箱格式不正确"}), HTTPStatus.BAD_REQUEST

    # 检查邮箱是否已注册
    if data_store.get_user_by_email(email):
        return jsonify({"error": "该邮箱已被注册"}), HTTPStatus.BAD_REQUEST

    # 发送验证码
    code = email_service.send_verify_code(email)
    if code:
        return jsonify({"message": "验证码已发送，请查收邮件"}), HTTPStatus.OK
    else:
        return jsonify({"error": "验证码发送失败，请检查邮箱配置或稍后重试"}), HTTPStatus.INTERNAL_SERVER_ERROR


@api_bp.post("/auth/register")
def register():
    """邮箱注册"""
    payload = request.get_json(silent=True)
    if not payload:
        return jsonify({"error": "Invalid JSON payload"}), HTTPStatus.BAD_REQUEST

    email = payload.get("email", "").strip().lower()
    password = payload.get("password", "")
    verify_code = payload.get("verify_code", "").strip()
    avatar = payload.get("avatar")
    bio = payload.get("bio")

    if not email or not password:
        return jsonify({"error": "邮箱和密码不能为空"}), HTTPStatus.BAD_REQUEST

    if not verify_code:
        return jsonify({"error": "验证码不能为空"}), HTTPStatus.BAD_REQUEST

    # 验证邮箱格式
    import re
    email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    if not re.match(email_pattern, email):
        return jsonify({"error": "邮箱格式不正确"}), HTTPStatus.BAD_REQUEST

    # 验证验证码
    if not email_service.verify_code(email, verify_code):
        return jsonify({"error": "验证码错误或已过期"}), HTTPStatus.BAD_REQUEST

    # 检查邮箱是否已注册
    if data_store.get_user_by_email(email):
        return jsonify({"error": "该邮箱已被注册"}), HTTPStatus.BAD_REQUEST

    # 从邮箱生成用户名（取@前面的部分）
    username = email.split("@")[0]

    user = data_store.create_user(
        {
            "username": username,
            "email": email,
            "password_hash": generate_password_hash(password),
            "avatar": avatar,
            "bio": bio,
        }
    )

    token = uuid4().hex
    data_store.create_session(token, user["id"])

    return jsonify({"user": _sanitize_user(user), "token": token}), HTTPStatus.CREATED


@api_bp.post("/auth/login")
def login():
    """登录（支持用户名或邮箱）"""
    payload = request.get_json(silent=True)
    if not payload:
        return jsonify({"error": "Invalid JSON payload"}), HTTPStatus.BAD_REQUEST

    username_or_email = payload.get("username", "").strip()
    password = payload.get("password", "")

    if not username_or_email or not password:
        return jsonify({"error": "用户名/邮箱和密码不能为空"}), HTTPStatus.BAD_REQUEST

    # 支持用户名或邮箱登录
    user = data_store.get_user_by_username(username_or_email)
    if not user or not check_password_hash(user["password_hash"], password):
        return jsonify({"error": "用户名/邮箱或密码错误"}), HTTPStatus.UNAUTHORIZED

    token = uuid4().hex
    data_store.create_session(token, user["id"])

    return jsonify({"user": _sanitize_user(user), "token": token})


@api_bp.route("/hello", methods=["GET"])
def hello_world():
    """
    返回 hello world 信息以及可选的名称参数。
    """
    name = request.args.get("name", "World")
    return jsonify({"message": f"Hello, {name}!"})


@api_bp.get("/sections")
def list_sections():
    """
    返回前端页面模块信息，便于动态渲染导航或首页入口。
    """
    return jsonify({"items": data_store.SECTIONS})


@api_bp.get("/content/introduction")
def get_introduction():
    """
    返回学科简介页面的核心数据。
    """
    return jsonify(data_store.get_introduction())


@api_bp.get("/content/founder")
def get_founder():
    """
    返回奠基人页面数据。
    """
    return jsonify(data_store.get_founder_profile())


@api_bp.get("/elements")
def list_elements():
    """
    返回信息工程五大要素列表，支持按 id 查询详情。
    """
    element_id = request.args.get("id")
    if element_id:
        element = data_store.get_element(element_id)
        if element is None:
            return jsonify({"error": "Element not found"}), HTTPStatus.NOT_FOUND
        return jsonify(element)
    return jsonify({"items": data_store.list_elements()})


@api_bp.get("/users/<int:user_id>")
def retrieve_user(user_id: int):
    user = data_store.get_user(user_id)
    if not user:
        return jsonify({"error": "User not found"}), HTTPStatus.NOT_FOUND
    return jsonify(_sanitize_user(user))


@api_bp.get("/users/me")
def retrieve_me():
    if not g.current_user:
        return jsonify({"error": "Unauthorized"}), HTTPStatus.UNAUTHORIZED
    return jsonify(_sanitize_user(g.current_user))


@api_bp.get("/users/me/posts")
def list_my_posts():
    """
    获取当前登录用户发布的所有帖子。
    需要认证: 是（需携带 Authorization 头）
    """
    if not g.current_user:
        return jsonify({"error": "Unauthorized"}), HTTPStatus.UNAUTHORIZED
    
    keyword = request.args.get("keyword")
    posts = data_store.list_posts(keyword=keyword, author_id=g.current_user["id"])
    return jsonify({"items": posts})


@api_bp.get("/users/me/comments")
def list_my_comments():
    """
    获取当前登录用户发表的所有评论。
    需要认证: 是（需携带 Authorization 头）
    """
    if not g.current_user:
        return jsonify({"error": "Unauthorized"}), HTTPStatus.UNAUTHORIZED
    
    comments = data_store.list_comments(author_id=g.current_user["id"])
    serialized = [_serialize_comment(comment) for comment in comments]
    return jsonify({"items": serialized})


@api_bp.get("/applications")
def list_applications():
    """
    返回应用领域案例列表，支持行业、标签与关键字过滤。
    """
    industry = request.args.get("industry")
    keyword = request.args.get("keyword")
    tag = request.args.get("tag")
    applications = data_store.list_applications(
        industry=industry,
        keyword=keyword,
        tag=tag,
    )
    return jsonify({"items": applications})


@api_bp.get("/future/insights")
def get_future_insights():
    """
    返回未来展望页面所需的趋势、指标等数据。
    """
    return jsonify(data_store.get_future_insights())


@api_bp.get("/meta/version")
def get_version_log():
    """
    返回版本历史信息。
    """
    return jsonify({"items": data_store.get_version_log()})


@api_bp.get("/meta/team")
def get_team_members():
    """
    返回项目团队成员信息。
    """
    return jsonify({"items": data_store.get_team_members()})


@api_bp.get("/content/carousel")
def get_carousel_cards():
    """
    返回首页轮播图卡片数据，包含背景图片等信息。
    """
    return jsonify({"items": data_store.get_carousel_cards()})


@api_bp.get("/posts")
def list_posts():
    """
    返回讨论区帖子列表，支持按关键字搜索和按作者ID过滤。
    """
    keyword = request.args.get("keyword")
    author_id = request.args.get("author_id")
    # 将author_id转换为整数（如果提供）
    author_id_int = int(author_id) if author_id and author_id.isdigit() else None
    posts = data_store.list_posts(keyword=keyword, author_id=author_id_int)
    return jsonify({"items": posts})


@api_bp.get("/posts/<int:post_id>")
def retrieve_post(post_id: int):
    """
    返回指定帖子的详情。
    """
    post = data_store.get_post(post_id)
    if post is None:
        return jsonify({"error": "Post not found"}), HTTPStatus.NOT_FOUND
    return jsonify(post)


@api_bp.post("/posts")
def create_post():
    """
    创建新的帖子。
    """
    payload = request.get_json(silent=True)
    if not payload:
        return jsonify({"error": "Invalid JSON payload"}), HTTPStatus.BAD_REQUEST

    required_fields = ["title", "content"]
    missing = [field for field in required_fields if not payload.get(field)]
    if missing:
        return (
            jsonify(
                {
                    "error": "Missing required fields",
                    "fields": missing,
                }
            ),
            HTTPStatus.BAD_REQUEST,
        )

    sentiment, sensitive_terms = nlp_service.screen_comment(payload["content"])
    if sentiment.label == "坏" or sensitive_terms:
        return (
            jsonify(
                {
                    "error": "内容审核未通过",
                    "label": sentiment.label,
                    "probabilities": sentiment.probabilities,
                    "sensitive_terms": sensitive_terms,
                }
            ),
            HTTPStatus.BAD_REQUEST,
        )

    # 如果用户已登录，使用当前用户的ID和用户名
    if g.current_user:
        payload["author_id"] = g.current_user["id"]
        if not payload.get("author"):
            payload["author"] = g.current_user["username"]

    new_post = data_store.create_post(payload)
    return jsonify(new_post), HTTPStatus.CREATED


@api_bp.post("/posts/<int:post_id>/replies")
def create_reply(post_id: int):
    """
    为指定帖子新增回复。
    """
    payload = request.get_json(silent=True)
    if not payload or not payload.get("content"):
        return jsonify({"error": "Reply content is required"}), HTTPStatus.BAD_REQUEST

    sentiment, sensitive_terms = nlp_service.screen_comment(payload["content"])
    if sentiment.label == "坏" or sensitive_terms:
        return (
            jsonify(
                {
                    "error": "内容审核未通过",
                    "label": sentiment.label,
                    "probabilities": sentiment.probabilities,
                    "sensitive_terms": sensitive_terms,
                }
            ),
            HTTPStatus.BAD_REQUEST,
        )

    reply = data_store.add_reply(post_id, payload)
    if reply is None:
        return jsonify({"error": "错误请求"}), HTTPStatus.NOT_FOUND

    return jsonify(reply), HTTPStatus.CREATED


@api_bp.post("/comments/analyze")
def analyze_comment():
    """
    分析评论情感倾向。
    """
    payload = request.get_json(silent=True)
    if not payload or not payload.get("content"):
        return (
            jsonify({"error": "缺少评论内容"}),
            HTTPStatus.BAD_REQUEST,
        )

    result, sensitive_terms = nlp_service.screen_comment(payload["content"])
    return jsonify(
        {
            "label": result.label,
            "confidence": result.confidence,
            "probabilities": result.probabilities,
            "sensitive_terms": sensitive_terms,
        }
    )


@api_bp.get("/comments")
def list_comments_endpoint():
    target_type = request.args.get("target_type")
    target_id = request.args.get("target_id")
    author_id = request.args.get("author_id")
    # 将author_id转换为整数（如果提供）
    author_id_int = int(author_id) if author_id and author_id.isdigit() else None
    comments = data_store.list_comments(
        target_type=target_type,
        target_id=target_id,
        author_id=author_id_int
    )
    serialized = [_serialize_comment(comment) for comment in comments]
    return jsonify({"items": serialized})


@api_bp.post("/comments")
def create_comment_endpoint():
    if not g.current_user:
        return jsonify({"error": "Unauthorized"}), HTTPStatus.UNAUTHORIZED

    payload = request.get_json(silent=True)
    if not payload:
        return jsonify({"error": "Invalid JSON payload"}), HTTPStatus.BAD_REQUEST

    target_type = payload.get("target_type")
    target_id = payload.get("target_id")
    content = (payload.get("content") or "").strip()

    if not target_type or not target_id or not content:
        return jsonify({"error": "target_type, target_id and content are required"}), HTTPStatus.BAD_REQUEST

    sentiment, sensitive_terms = nlp_service.screen_comment(content)
    if sentiment.label == "坏" or sensitive_terms:
        return (
            jsonify(
                {
                    "error": "内容审核未通过",
                    "label": sentiment.label,
                    "probabilities": sentiment.probabilities,
                    "sensitive_terms": sensitive_terms,
                }
            ),
            HTTPStatus.BAD_REQUEST,
        )

    comment = data_store.create_comment(
        {
            "author_id": g.current_user["id"],
            "target_type": target_type,
            "target_id": target_id,
            "content": content,
        }
    )
    return jsonify(_serialize_comment(comment)), HTTPStatus.CREATED


@api_bp.get("/search")
def search():
    """
    在模块、帖子、应用等资源中进行关键词搜索。
    """
    keyword = request.args.get("keyword")
    if not keyword:
        return jsonify({"error": "keyword is required"}), HTTPStatus.BAD_REQUEST

    results = data_store.search_all(keyword)
    return jsonify(results)

